---
name: Your Custom Knob
menu: Knobs
route: /writing-your-own-custom-knob
---

import { useState } from "react";
import { Playground, PropsTable } from "docz";
import { KnobFrame } from "../../src/lib";
import useChartKnob from "../../example/custom-chart-knob";

## Writing a custom Knob

Retoggle allows you to add your own knobs to the Inspector.

A custom knob comprises of two parts

- A component to render in the inspector panel
- A custom hook to manage state

## The API

```javascript
import { useInspector } from "retoggle";
```

- `const inspector = useInspector()` - Gets the current inspector state from the context.

- `inspector.addKnobRenderer(type, Component)` - Registers a knob renderer component to the inspector panel.

  - `type`: Knob type. This is a string. Should be unique across knobs.
  - `Component`: The component constructor.

```javascript
import Component from './myComponent';
inspector.addKnobRenderer("chart", Component);
```

- `inspector.setKnob(props)` - You would call this method to update your knob. The following are required props.

  - `name`: The name of your knob.
  - `type`: Type of the knob.

```javascript
inspector.setKnob({
  name: "Custom knob sample",
  type: "chart",
  data: {value: 5}
});
```

- `inspector.removeKnob(name)` - You would call this method remove your knob from the inspector. Usually when your hook unmounts.
  - `name`: The name of your knob.

```
inspector.removeKnob("Custom knob sample")
```

## A sample implementation

This example knob implementation can be found in [src/example/custom-chart-knob](https://github.com/Raathigesh/storyhooks/blob/master/src/example/custom-chart-knob/index.ts).

### The Component of the Knob

This component will receive all the props passed to `setKnob()`. Nothing special here. An ordinary react component.

```javascript
import React from "react";
import styled from "styled-components";
import { Activity } from "react-feather";
import { Sparklines, SparklinesLine, SparklinesSpots } from "react-sparklines";
import { KnobFrame } from "retoggle";

const Container = styled.div`
  display: flex;
  width: 100%;
  margin-top: 5px;

  svg {
    width: 100%;
    height: 50px;
  }
`;

export default function Chart({ data }) {
  return (
    <KnobFrame
      label="This is a custom knob"
      direction="column"
      icon={<Activity size={11} />}
    >
      <Container>
        <Sparklines data={data} limit={20}>
          <SparklinesLine color="#1c8cdc" />
          <SparklinesSpots />
        </Sparklines>
      </Container>
    </KnobFrame>
  );
}
```

### The custom knob hook

```javascript
import { useState, useEffect } from "react";
import { useInspector } from "retoggle";
import Component from "./component";

const KnobType = "chart";

export default function useChartKnob(name: string, value: any) {
  const [data, setData] = useState([]);
  const inspector = useInspector();

  // Registering the knob renderer
  inspector.addKnobRenderer(KnobType, Component);

  useEffect(
    () => {
      const randomNumber = Math.floor(Math.random() * 6) + 1;
      setData([...data, randomNumber]);

      // Passing the props to the renderer component
      inspector.setKnob({
        name,
        type: KnobType,
        data
      });
    },
    [value]
  );

  useEffect(() => {
    // cleaning up before unmounting
    return () => inspector.removeKnob(name);
  }, []);
}
```

## Helper KnobFrame Component

Retoggle provides a helper `KnobFrame` component you can use with your custom knobs. The frame provides a label and a placeholder for icon.

```javascript
import { KnobFrame } from "retoggle";
import { Activity } from "react-feather";

<KnobFrame
  label="This is a custom knob"
  direction="column"
  icon={<Activity size={11} />}
/>;
```

<PropsTable of={KnobFrame} />
